#!/usr/bin/env node
const { execSync } = require('child_process');
const { OpenAI } = require('openai')
const { default: inquirer } = require('inquirer');
const path = require('path');
const fs = require('fs');

async function main() {
    const chalk = (await import('chalk')).default;
    const branch = await execSync('git branch --show-current').toString().trim();

    const config = {
        // apiKey: process.env.XXX_API_KEY,
        // baseURL: process.env.XXX_BASE_URL,
        // modal: process.env.XXX_MODEL,
        // apiKey: 'sk-ade9753627f04d7c8ae3b41ee5670ab1',
        // baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
        // modal: 'qwen-plus',
        apiKey: '572fd2fd-0cc0-443c-a278-6e5271d942ed',
        baseURL: 'https://ark.cn-beijing.volces.com/api/v3',
        modal: 'deepseek-v3-1-terminus',
    }

    const client = new OpenAI({
        apiKey: config.apiKey,
        baseURL: config.baseURL,
    });
    console.log('node version:' + await execSync('node -v').toString().trim());

    // 检查没有追踪的新文件
    let untrackedFiles = await execSync('git ls-files --others --exclude-standard').toString().trim().split('\n')
    untrackedFiles = untrackedFiles.filter(f => f.trim() !== '')
    if (untrackedFiles.length > 0) {
        // 提示是否添加到暂存区
        const answer = await inquirer.prompt([
            {
                type: 'confirm',
                name: 'add',
                message: `检测到未追踪文件 ${untrackedFiles.join(', ')}, 是否添加到暂存区? 如不添加将无法获取到未追踪文件的内容`,
                default: true
            }
        ]);
        if (answer.add) {
            await execSync(`git add ${untrackedFiles.join(' ')}`);
        }
    }

    const diffContent = await execSync(`git diff HEAD -- . ':!yarn.lock' ':!package-lock.json' | head -c 3000`).toString()

    let currentProjectPrompt = '未设置'
    // 读取.vscode/aiCommitPrompt.txt
    try {
        currentProjectPrompt = await fs.readFileSync('.vscode/aiCommitPrompt.txt', 'utf-8');
    } catch (error) {
    }
    
    const getCommitMessage = (head = 0) => { 
        try {
            return execSync(`git show HEAD~${head} --pretty=%B --no-patch`).toString().trim()
        }catch (error) {
            return ''
        }
    };

    const content =
        `按以下规则生成git提交信息

规则:
- 务必关注多轮对话的用户输入提示信息，再返回矫正后的提交信息
- 根据下列提供的线索，生成提交信息
- 格式注意尽量与最近一次提交保持一致
- 生成的信息尽量保证简洁
- 仅需返回生成的 commit 内容

<section title="用户输入的提示信息(process.argv)">
${process.argv}

process.argv 是用户的命令行参数，部分信息需要忽略，你自行判断是否有参考价值。
</section>

<section title="当前分支">
${branch}
</section>

<section title="当前项目提示词">
${currentProjectPrompt}
</section>

<section title="最近提交内容 HEAD">
${getCommitMessage(0)}
</section>

<section title="最近提交内容 HEAD~1">
${getCommitMessage(1)}
</section>

<section title="最近提交内容 HEAD~2">
${getCommitMessage(2)}
</section>

<section title="最近提交内容 HEAD~3">
${getCommitMessage(3)}
</section>

<section title="最近提交内容 HEAD~4">
${getCommitMessage(4)}
</section>

<section title="git status">
${execSync('git status -s').toString().trim()}
</section>

<section title="变更内容">
${diffContent}
</section>
`
    function writeLog(content, filename = 'log.txt') {
        try {
            const logPath = path.join(__dirname, filename);
            const dir = path.dirname(logPath);

            // 确保目录存在
            if (!fs.existsSync(dir)) {
                fs.mkdirSync(dir, { recursive: true });
            }

            // 写入内容（会自动创建文件）
            fs.writeFileSync(logPath, content + '\n\n', { flag: 'w' });

            console.log(`日志已写入: ${logPath}`);
        } catch (error) {
            console.error('写入日志失败:', error);
        }
    }
    writeLog(content)

    const messages = [{ role: "system", content }]

    const send = async () => {
        const completion = await client.chat.completions.create({
            messages: messages,
            model: config.modal,
            stream: true,
        });

        process.stdout.write('\n');
        let rs = ''
        // 逐字输出到终端
        for await (const part of completion) {
            const curr = part.choices[0].delta.content
            rs += curr
            process.stdout.write(chalk.green(curr));
        }
        process.stdout.write('\n\n');

        inquirer.prompt([
            {
                type: 'list',
                name: 'action',
                message: '请选择操作:',
                choices: [
                    { name: '仅提交', value: 'commit' },
                    { name: '提交并推送', value: 'commit-push' },
                    { name: '追加提示信息', value: 'generate' },
                    { name: '退出 [ctrl+c]', value: 'exit' }
                ],
                default: 'commit-push'
            }
        ]).then(async (answers) => {
            switch (answers.action) {
                case 'commit':
                    console.log(chalk.blue('正在执行 git add . ...'));
                    await execSync('git add .', { stdio: 'inherit' }); // 添加 stdio: 'inherit'
                    console.log(chalk.blue('正在执行 git commit ...'));
                    await execSync(`git commit -m "${rs}"`, { stdio: 'inherit' }); // 添加 stdio: 'inherit'
                    console.log(chalk.green('提交成功！'));
                    break;
                case 'commit-push':
                    console.log(chalk.blue('正在执行 git add . ...'));
                    await execSync('git add .', { stdio: 'inherit' }); // 添加 stdio: 'inherit'
                    console.log(chalk.blue('正在执行 git commit ...'));
                    await execSync(`git commit -m "${rs}"`, { stdio: 'inherit' }); // 添加 stdio: 'inherit'
                    console.log(chalk.blue('正在执行 git push ...'));
                    await execSync(`git push`, { stdio: 'inherit' }); // 添加 stdio: 'inherit'
                    console.log(chalk.green('提交并推送成功！'));
                    break;
                case 'generate':
                    messages.push({ role: "assistant", content: rs })
                    // 先让用户输入提示信息
                    const tip = await inquirer.prompt([
                        {
                            type: 'input',
                            name: 'tip',
                            message: '请输入提示信息:',
                        }
                    ]);
                    // 提示信息用用户角色追加到 messages
                    messages.push({ role: "user", content: tip.tip });
                    await send();
                    break;
                case 'exit':
                    console.log('退出...');
                    break;
            }
        }).catch(async (e) => {
            console.error(e);
            // 报错了，将rs复制到剪贴板
            execSync(`echo "${rs.trim()}" | pbcopy`);
            console.log(chalk.yellow('执行失败，已复制到剪贴板'));
            // 暂停，按任意键退出
            console.log(chalk.yellow('按任意键退出...'));
            await inquirer.prompt([
                {
                    type: 'input',
                    name: 'exit',
                    message: '按任意键退出...',
                }
            ]).then(() => {
                process.exit();
            });
        });
    }
    await send();
}

main()